#pragma once

template <class T>
class Vector3
{
public:
    // constructor/destructor
    Vector3() {}
	Vector3( T _x, T _y, T _z ) :
        x(_x), y(_y), z(_z)
    {}
	Vector3(const Vector3<T>& other);
    ~Vector3() {}

    
    inline Vector3<T>& operator=(const Vector3<T>& other);
    inline T& operator[](unsigned int i);

	// utils
    inline T length() const;
    inline T lengthSquared() const;
    //T distance(const Vector3<T>& p0, const Vector3<T>& p1);
    //T distanceSquared( const Vector3<T>& p0, const Vector3<T>& p1 );

    // comparison
	inline bool operator==(const Vector3<T>& other) const;
	inline bool operator!=(const Vector3<T>& other) const;
    inline bool isZero() const;

    // manipulators
    inline void set(T _x, T _y, T _z);
    inline void zero(); // sets all elements to 0
    inline void normalize();   // sets to unit vector

    // addition/subtraction
    inline Vector3<T> operator+(const Vector3<T>& other) const;
    inline Vector3<T>& operator+=(const Vector3<T>& other);
    inline Vector3<T> operator-(const Vector3<T>& other) const;
    inline Vector3<T>& operator-=(const Vector3<T>& other);
    inline Vector3<T> operator-() const;
    inline Vector3<T> operator*(T scalar) const;
	inline Vector3<T> operator/(T scalar) const;
    inline Vector3<T>& operator*=(T scalar);
    
    // dot product/cross product
    inline T dot(const Vector3<T>& vector) const;
    static T dot(const Vector3<T>& vector1, const Vector3<T>& vector2);
    inline Vector3<T> cross(const Vector3<T>& vector) const;
    static Vector3<T> cross(const Vector3<T>& vector1, const Vector3<T>& vector2);

    // member variables
    T x, y, z;
};

static Vector3<float> xAxisf(1.0f,0,0);
static Vector3<float> yAxisf(0,1.0f,0);
static Vector3<float> zAxisf(0,0,1.0f);
static Vector3<float> originf(0,0,0);

#include "Vector3.inl"

typedef Vector3<float> vec3f;